#ifndef _PCAP_PARSE_H
#define _PCAP_PARSE_H

#include <stdio.h>
#include <map>
#include <list>
#include <memory>
//#include "payloadBase.h"

using std::map;
using std::shared_ptr;

#define MAX_FILENAME_PATH 260

enum { kRtpCsrcSize = 15 }; // RFC 3550 page 13



struct RTPHeaderExtension {
    RTPHeaderExtension()
        : hasTransmissionTimeOffset(false),
        transmissionTimeOffset(0),
        hasAbsoluteSendTime(false),
        absoluteSendTime(0),
        hasAudioLevel(false),
        audioLevel(0) {}

    bool hasTransmissionTimeOffset;
    int32_t transmissionTimeOffset;
    bool hasAbsoluteSendTime;
    uint32_t absoluteSendTime;

    // Audio Level includes both level in dBov and voiced/unvoiced bit. See:
    // https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
    bool hasAudioLevel;
    uint8_t audioLevel;
};

struct RTPHeader {
    RTPHeader()
        : markerBit(false),
        payloadType(0),
        sequenceNumber(0),
        timestamp(0),
        ssrc(0),
        numCSRCs(0),
        paddingLength(0),
        headerLength(0),
        payload_type_frequency(0),
        extension() {
        memset(&arrOfCSRCs, 0, sizeof(arrOfCSRCs));
    }

    bool markerBit;
    uint8_t payloadType;
    uint16_t sequenceNumber;
    uint32_t timestamp;
    uint32_t ssrc;
    uint8_t numCSRCs;
    uint32_t arrOfCSRCs[kRtpCsrcSize];
    uint8_t paddingLength;
    uint16_t headerLength;
    int payload_type_frequency;
    RTPHeaderExtension extension;
};

enum ePktType
{
    ePktNaked,  // 一般用于只有音频的模式，没有拆包分片
    ePkt264,
    ePkt265,
    ePktPsVideo,
    ePktPsAudio,
//     ePktRed265,
//     ePktRed264
};

class CPcapParse
{
public:
    CPcapParse();
    virtual ~CPcapParse();
    // 输入文件名，以及每个包数据起始的偏移位置，偏移位置通过wireshark界面查看获得，通常为42或44
    int init(const char *pchPcapFile);
    // 类似于fread, 顺序读取
    int copyPktData(char *pchData, size_t bufLen, size_t &dataLen, uint64_t *pMs);
    void reset();
private:
    typedef struct pcapFileHeader
    {
        unsigned char   magic[4];
        unsigned short  version_major;
        unsigned short  version_minor;
        int             thiszone;      /*时区修正*/
        unsigned int   sigfigs;       /*精确时间戳*/
        unsigned int   snaplen;       /*抓包最大长度*/
        unsigned int   linktype;      /*链路类型*/
    } pcapFileHeader_t;

    pcapFileHeader_t m_FileHeader;

    /*pcap packet header*/
    typedef struct pcapPkthdr
    {
        unsigned int    seconds;     /*秒数*/
        unsigned int    u_seconds;   /*毫秒数*/
        unsigned int    caplen;      /*数据包长度*/
        unsigned int    len;         /*文件数据包长度*/
    } pcapPkthdr_t;

    FILE *m_fp;
    size_t m_sizePktOffset;
};

bool rtpParse(RTPHeader& header, const void *p, size_t sizeLen);

class rtpPacket
{
public:
    rtpPacket();
    virtual ~rtpPacket();
    int init(const char *pchBuf, size_t sizeLen, uint64_t ts);
    const char *getHeader() const { return &m_buf[0]; }
    size_t getPktLen() const { return m_len;  } 
    uint64_t getTs(){ return m_ts; }
private:
    char m_buf[2000];
    size_t m_len;
    uint64_t m_ts;  // 时间戳wireshark 抓包
};

class CRtpManage
{
public:
    CRtpManage();
    virtual ~CRtpManage();
    // 输入已经过滤pcap 抓包文件,内部不进行ssrc 过滤
    int init(const char *inFile);

    // 发送给远端的网络
    int netPlay(const int8_t * remoteAddr, uint16_t remotePort, uint16_t localPort);
    // 获取pcap 的map 数据
    void getMap(std::map<unsigned int, shared_ptr<rtpPacket> >& omapRtp);
    // 获取pcap 的list 数据
    void getList(std::list<shared_ptr<rtpPacket> >& olistRtp);
    // 清除map list, 重新init
    void reset();
private:

    int proc();
    typedef map<unsigned int, shared_ptr<rtpPacket> > mapRtp; 
    char m_inFile[MAX_FILENAME_PATH];
    CPcapParse m_pcap;
    mapRtp  m_mapRtp; // 有重排序
    std::list<shared_ptr<rtpPacket>> m_listRtp; // 没有重排序

};


#endif

